
#include "EventLoop.h"
// #include "hasync.h"  // import hv::async
#include "config_helper.h"
#include "db/eventrecords.h"
#include "db/miscstorage.h"
#include "devices_collect.h"
#include "directory_cleaner.h"
#include "hlog.h"
#include "hloop.h"
#include "hmain.h"
#include "http/router.h"
#include "hversion.h"
#include "utils/auth.h"

using namespace hv;

HttpServer g_http_server;
HttpService g_http_service;

static const option_t long_options[] = {
    {'h', "help",    NO_ARGUMENT,       "Print this information"                        },
    {'v', "version", NO_ARGUMENT,       "Print version"                                 },
    {'c', "confile", REQUIRED_ARGUMENT, "Set configure file, default etc/{program}.conf"},
    {'d', "daemon",  NO_ARGUMENT,       "Daemonize"                                     }
};

int main(int argc, char** argv) {
    // memcheck atexit
    HV_MEMCHECK;

    main_ctx_init(argc, argv);
    if (argc == 1) {
        print_help(long_options, ARRAY_SIZE(long_options));
        exit(10);
    }

    int ret = parse_opt_long(argc, argv, long_options, ARRAY_SIZE(long_options));
    if (ret != 0) {
        print_help(long_options, ARRAY_SIZE(long_options));
        exit(ret);
    }

    // help
    if (get_arg("h")) {
        print_help(long_options, ARRAY_SIZE(long_options));
        exit(0);
    }

    // version
    if (get_arg("v")) {
        print_version();
        exit(0);
    }

    conf_ctx_init(&g_conf_ctx);
    const char* confile = get_arg("c");
    if (confile) {
        strncpy(g_main_ctx.confile, confile, sizeof(g_main_ctx.confile));
    }
    parse_confile(g_main_ctx.confile);

    // daemon
    if (get_arg("d")) {
        // nochdir, noclose
        int ret = daemon(1, 1);
        if (ret != 0) {
            printf("daemon error: %d\n", ret);
            exit(-10);
        }
    }

    // pidfile 默认在logs目录下
    create_pidfile();

    // http_server
    Router::Register(g_http_service, &g_conf_ctx);
    g_http_server.registerHttpService(&g_http_service);
    g_http_server.port = g_conf_ctx.service_port;

    MiscStorageHandler->open(g_conf_ctx.db_path + "/miscstorage.db");
    EventRecordsHandler->open(g_conf_ctx.db_path + "/eventrecords.db");

    DirectoryCleaner cleaner(g_conf_ctx.records_path, g_conf_ctx.records_size);
    g_http_server.onWorkerStart = [&] {
        EventLoopPtr loop = g_http_server.loop();

        hsignal_add(loop->loop(), on_signal, SIGINT);

        // httpserver.cpp里会调用hlog_disable_fsync()所以要想同步到文件需要重新使能
        // if (g_conf_ctx.log_fsync) {
        //     hlog_enable_fsync();
        // }
        loop->setInterval(3000, [&](TimerID id) { hlog_fsync(); });

        AuthHandler->update_token(loop);

        // 每半小时清理一次
        constexpr uint32_t CLEAN_INTERVAL_MS = 1800 * 1000;
        loop->setInterval(CLEAN_INTERVAL_MS, [&](TimerID id) {
            // hlogi("clear old files now");
            cleaner.cleanOldFiles();
        });

        loop->setInterval(100, std::bind(Router::car_heartbeat_check, std::placeholders::_1, device_collect));
    };

    // 立即执行一次清理
    cleaner.cleanOldFiles();

    g_http_server.run();
    return 0;
}
